<script setup lang="ts">
import { reactive, ref, watch } from "vue";
import { zxcvbn } from "@zxcvbn-ts/core";
import { isAllEmpty, copyTextToClipboard } from "@pureadmin/utils";
import { message } from "@/utils/message";
import { genRandomPassword } from "@/utils/truncate";
import $request from "./utils/request";

// 定义事件
const emit = defineEmits(["ok"]);

// 状态参数
const state = reactive({
  // 当前编辑的ID
  id: 0,
  // 标题
  title: "",
  // 密码类型
  passType: "",
  // 加载中
  isLoading: false,
  // 提交中
  confirmLoading: false,
  // 是否显示
  visible: false
});

// 密码（用户输入）
const password = ref("");

// 当前密码强度（0-4）
const curScore = ref();

const pwdProgress = [
  { color: "#e74242", text: "非常弱" },
  { color: "#EFBD47", text: "弱" },
  { color: "#ffa500", text: "一般" },
  { color: "#1bbf1b", text: "强" },
  { color: "#008000", text: "非常强" }
];

// 弹窗开启
const handleOpen = async (options: FormModalOptions) => {
  state.passType = "password";
  password.value = "";
  state.isLoading = true;
  state.confirmLoading = false;
  if (typeof options.id === "number" && options.id) {
    state.id = options.id;
    const userData = await $request.get.detail(options.id);
    state.title = `重置 ${userData.username} 用户的密码`;
    state.visible = true;
    setTimeout(() => {
      state.isLoading = false;
    }, 0);
  } else {
    message("数据读取失败，请刷新页面后重试", { type: "error" });
  }
};

// 随机生成密码
const handleRandom = () => {
  password.value = genRandomPassword();
  // 打开下方注释后，如果生成了随机密码会自动去除掩码（清空后取消）
  // state.passType = "text";
  if (copyTextToClipboard(password.value)) {
    message("随机密码已复制到剪切板", { type: "success" });
  }
};

// 提交
const handleSubmit = async () => {
  try {
    state.confirmLoading = true;
    if (!password.value) {
      message("请输入密码", { type: "error" });
      return;
    }
    const data = {
      password: password.value
    };
    await $request.put.setPassword(state.id, data);
    message("密码修改成功", { type: "success" });
    emit("ok");
    state.visible = false;
  } finally {
    state.confirmLoading = false;
  }
};

// 计算密码强度
watch(
  password,
  val => (curScore.value = isAllEmpty(val) ? -1 : zxcvbn(val).score)
);

defineExpose({
  handleOpen
});
</script>

<template>
  <plus-dialog
    v-model="state.visible"
    :title="state.title"
    closeOnClickModal
    cancel-text="取消"
    confirm-text="确定"
    :confirm-loading="state.confirmLoading"
    @confirm="handleSubmit"
  >
    <div class="mb-5">
      <el-input
        v-model="password"
        class="w-full"
        clearable
        :show-password="state.passType === 'password'"
        :type="state.passType"
        placeholder="请输入新密码"
        @clear="() => (state.passType = 'password')"
      >
        <template #append>
          <el-button type="primary" @click="handleRandom">随机密码</el-button>
        </template>
      </el-input>
    </div>
    <div class="flex">
      <template v-for="(item, index) of pwdProgress" :key="index">
        <div class="w-[19vw]" :style="{ marginLeft: index !== 0 ? '4px' : 0 }">
          <el-progress
            striped
            striped-flow
            :duration="curScore === index ? 6 : 0"
            :percentage="curScore >= index ? 100 : 0"
            :color="item.color"
            :stroke-width="10"
            :show-text="false"
          />

          <p
            class="text-center"
            :style="{ color: curScore === index ? item.color : '' }"
          >
            {{ item.text }}
          </p>
        </div>
      </template>
    </div>
  </plus-dialog>
</template>

<style lang="scss" scoped>
//
</style>
